git push origin HEADの”HEAD”とgit pull origin HEADの”HEAD”は別物だという話
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、git push origin HEAD
のHEADとgit pull origin HEAD
のHEADは別物だということを認識できておらず、やらかしてしまった話です。
やらかした概要
GitHub上のRepositoryで管理しているソースコードに対して私を含めた複数人で作業をしていたところ、次のようなやらかしをしてしまいました。
- コミットAからCheckoutした
topic1
ブランチで作業をする。(コミットB、Cの追加) - 別のユーザーが同じくコミットAからCheckoutした
tipic2
ブランチで作業をし、main
ブランチにマージする。(コミットD、E、Fの追加) git pull origin HEAD
を実行してローカルの変更をPullする。- これにより、OriginのHEADがローカルブランチでRebaseされてしまう。
この結果、ローカルブランチをPushできなくなりました。(ここでForce PushをするとOrigin側で不具合が生じる場合がある)
詳細
1.,2.,3.の詳細です。
1.では、私がコミットAからCheckoutしたtopic1
ブランチで作業をしました。(コミットB、C)
一方2.では、別のユーザーが同じくコミットAからCheckoutしたtipic2
ブランチで作業をし、main
ブランチにマージしました。(コミットD、E、F)
この時点でのCommit Graphは次のようになります。
3.で、私がgit pull origin HEAD
を実行しました。これにより、オリジンのHEADがローカルブランチにマージされました。
これによりローカルブランチをリモートにプッシュができなくなってしまいました。(やらかした!)
$ git push origin HEAD To https://github.com/cm-rwakatsuki/test.git ! [rejected] HEAD -> topic1 (non-fast-forward) error: failed to push some refs to 'https://github.com/cm-rwakatsuki/test.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
原因
git pull origin HEAD
によりPullされるのは、Origin側のデフォルトブランチの先頭になるためです。普段ローカルでの作業の変更をPushする際にgit push origin HEAD
と実行していたため、その手癖でPull時にもHEAD
を指定してしまっていました。
対策
git pull origin HEADをしないように気をつける
リモートブランチ側での変更(Pull RequestでChange Suggestionを取り込んだ時など)をローカルに反映させたい時は、git pull origin <topic branch>
を使うようにしましょう。
RebaseではなくMergeするようにする
Pullする際にOriginから取得した変更をローカルに対してRebaseするかどうかを設定で指定できます。現状の設定を確認する場合はgit config --get pull.rebase
を実行します。true
ならRebase、false
ならMergeされるようになっています。
# trueの場合はRebaseされるようになっている $ git config --get pull.rebase true
Mergeされるようにしたい場合は、git config pull.rebase false
を実行します。
下記はpull.rebase false
の場合の挙動です。pull.rebase true
の場合と挙動が異なることが分かります。
Pushも問題なくできます。(Pull RequestにMerge Commitが反映された様子)
参考
以上